#include <cstdlib>
#include <cctype>
#include <cstring>
#include <string>
#include <sstream>
#ifndef __OPTIONS_HPP__
#define __OPTIONS_HPP__

/**
 * Server 起動オプションの読み取りを行う．
 */
class Options {
private:
  int         _port;
  int         _worker_num;
  std::string _doc_root;
  bool        _daemon;
  std::string _log_path;
  std::string _error;

public:
  Options(int argc, char* argv[])
      : _port(8888)
      , _worker_num(10)
      , _doc_root(".")
      , _daemon(false)
      , _log_path("./dust.log") {
    parse(argc, argv);
  }

  // getter
  int port() const { return this->_port; }
  int worker_num() const { return this->_worker_num; }
  const std::string& doc_root() const { return this->_doc_root; }
  bool is_daemon() const { return this->_daemon; }
  const char* log_path() const { return this->_log_path.c_str(); }

  // error
  bool has_error() const { return !this->_error.empty(); }
  const char* error() const { return this->_error.c_str(); }

  // debug
  const std::string to_string() const {
    std::ostringstream ss;
    ss << "port=" << port()
       << ", worker_num=" << worker_num()
       << ", doc_root=" << doc_root()
       << ", daemon=" << is_daemon()
       << ", log_path=" << log_path();
    return ss.str();
  }

private:
  bool is_integer(const char* src) {
    while (src != NULL && *src != '\0' && isdigit(*src++));
    return *src == '\0';
  }

  bool parse(int argc, char* argv[]) {
    for (int i=0; i<argc; ++i) {
      const char* arg = argv[i];
      if (strcmp(arg, "-d") == 0) {
        this->_daemon = true;
      } else if (strcmp(arg, "-p") == 0) {
        const char* val = argv[++i];
        if (is_integer(val)) {
          this->_port = atoi(val);
        } else {
          set_error_message("-p", val);
          return false;
        }
      } else if (strcmp(arg, "--worker-num") == 0) {
        const char* val = argv[++i];
        if (is_integer(val)) {
          this->_worker_num = atoi(val);
        } else {
          set_error_message("--worker_num", val);
          return false;
        }
      } else if (strcmp(arg, "--doc-root") == 0) {
        const char* val = argv[++i];
        this->_doc_root = std::string(val);
      } else if (strcmp(arg, "--log-file") == 0) {
        const char* val = argv[++i];
        this->_log_path = std::string(val);
      }
    }
    return true;
  }
  void set_error_message(const char* param, const char* val) {
    std::ostringstream ss;
    ss << "illegal '" << param << "' argument. value=" << val;
    this->_error = ss.str();
  }
};
#endif
